import sys
import json
import dispatcher as dp
import world

from twisted.internet import reactor
from twisted.python import log
from twisted.web.server import Site
from twisted.web.static import File
from mongoengine import connect
# from threading import Timer

from autobahn.twisted.websocket import WebSocketServerFactory, \
    WebSocketServerProtocol, \
    listenWS


# Client
class BroadcastServerProtocol(WebSocketServerProtocol):

    def onOpen(self):
        self.factory.register(self) # received an client then register it

    # When message comes dispatcher to do dividual things
    def onMessage(self, payload, isBinary):
        if not isBinary:
            # msg = "{} from {}".format(payload.decode('utf8'), self.peer)
            # self.factory.broadcast(msg)
            data = json.loads(payload.decode('utf8'))
            dp.dispatch(data,self)
            # print str(data)

    def connectionLost(self, reason):
        WebSocketServerProtocol.connectionLost(self, reason)
        self.factory.unregister(self)
        #TODO: Change player status to offline
        dp.offlinePlayer(self)


# Client Factory
class BroadcastServerFactory(WebSocketServerFactory):

    """
    Simple broadcast server broadcasting any message it receives to all
    currently connected clients.
    """

    def __init__(self, url):
        WebSocketServerFactory.__init__(self, url)
        self.clients = []
        # World main loop
        self.worldTime = 0
        self.updateWorld()

    def register(self, client):
        if client not in self.clients:
            print("registered client {}".format(client.peer))
            self.clients.append(client)

    def unregister(self, client):
        if client in self.clients:
            print("unregistered client {}".format(client.peer))
            self.clients.remove(client)

    def broadcast(self, msg):
        print("broadcasting message '{}' ..".format(msg))
        for c in self.clients:
            c.sendMessage(msg.encode('utf8'))
            print("message sent to {}".format(c.peer))
    
    def updateWorld(self): 
        world.update(self.worldTime, self)
        self.worldTime = self.worldTime + 1 # Time inc
        # Test
        self.broadcast(json.dumps({"worldTime": self.worldTime}))
        reactor.callLater(60, self.updateWorld)



if __name__ == '__main__':

    # DB connect
    connect('sbo',host='192.154.214.165',username='kobako', password='123', authentication_source='admin')

    log.startLogging(sys.stdout)

    ServerFactory = BroadcastServerFactory

    server = ServerFactory(u"ws://127.0.0.1:9000")
    server.protocol = BroadcastServerProtocol
    listenWS(server)


    reactor.run()